package com.pattern.strategy;

import com.pattern.strategy.service.CalculateStrategy;
import com.pattern.strategy.service.impl.BusStrategy;

/**
 * 策略模式属于对象的行为模式。
 * 其用意是针对一组算法，将每一个算法封装到具有共同接口的独立的类中，从而使得它们可以相互替换。
 * 策略模式使得算法可以在不影响到客户端的情况下发生变化。
 *
 * 策略模式是对算法的包装，是把使用算法的责任和算法本身分割开来，委派给不同的对象管理。
 * 策略模式通常把一个系列的算法包装到一系列的策略类里面，作为一个抽象策略类的子类。
 * 用一句话来说，就是：“准备一组算法，并将每一个算法封装起来，使得它们可以互换”。
 *
 * 这个模式涉及到三个角色：
 　　●　环境(Context)角色：持有一个Strategy的引用。
 　　●　抽象策略(Strategy)角色：这是一个抽象角色，通常由一个接口或抽象类实现。此角色给出所有的具体策略类所需的接口。
 　　●　具体策略(ConcreteStrategy)角色：包装了相关的算法或行为。
   策略模式的使用场景：
     1）针对同一种问题的多种处理方式、仅仅是因为具体行为有差别时，
     2）需要安全的封装多种同一类型的操作时
     3）出现同一抽象类有多个子类，而又需要使用if-else或者switch-case来选择具体子类时。
 *
 * 这样即使需要添加出租车的价格计算，只需要简单的新建一个类，
 * 让其继承自CalculateStrategy接口并实现其中的方法即可
 *
 * PS: 策略模式经常使用，Springboot项目中经常事一个接口有多个不同的实现类，
 *      通过@qualifier进行注入不同的实现类。
 */
public class TranficCalculator {

    CalculateStrategy mStrategy;

    public static void main(String[] args) {
        TranficCalculator calculator = new TranficCalculator();
        //设置计算策略
        calculator.setStrategy(new BusStrategy());
        //计算价格
        System.out.println("公交车乘10公里的价格：" + calculator.calculatePrice(10));

    }

    public void setStrategy(CalculateStrategy mStrategy) {
        this.mStrategy = mStrategy;
    }
    public int calculatePrice(int km) {
        return mStrategy.calculatePrice(km);
    }

}
